﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ProjetS5
{
    public class Character : Mover
    {
        public Character(Vector2 Position, Vector2 Orientation, byte Level, DB_CharacterRace CharacterRace)
            : base(Position, Orientation)
        {
            level = Level;
            characterRace = CharacterRace;

            pointBars = new Dictionary<DB_PointBar, int>();
            baseStatistics = new Dictionary<DB_Statistic, float>();
            effects = new List<Effect>();
            abilities = new List<Ability>();
            calculatedStatistics = new Dictionary<DB_Statistic, float>();
            isDead = false;
        }

        private float howEffectsAffect(String statistic)
        {
            float sum = 0;
            foreach(Effect effect in effects)
            {
                sum += effect.HowItAffect(statistic);
            }
            return sum; 
        }

        protected void setBaseStats(Dictionary<DB_Statistic, KeyValuePair<float, float>> baseStats)
        {
            foreach (KeyValuePair<DB_Statistic, KeyValuePair<float, float>> statistic in baseStats)
            {
                baseStatistics.Add(statistic.Key, statistic.Value.Key + (float)Math.Pow(statistic.Value.Value, level));
            }
        }
        protected void calculateNewStats(Equipment stuff, String className)
        {
            foreach (KeyValuePair<DB_Statistic, float> statistic in baseStatistics)
            {
                float value = statistic.Value;
                float forOnePoint = 0;

                switch (statistic.Key.Name)
                {
                    case "force":
                    case "endurance":
                    case "agilité":
                    case "dextérité":
                    case "esprit":
                    case "armure":
                    case "résistance":
                        value += stuff.GetSum(statistic.Key.Name) + howEffectsAffect(statistic.Key.Name);
                        break;
                    case "puissance":
                        switch (className)
                        {
                            case "guerrier": forOnePoint = 2; break;
                            case "chasseur": forOnePoint = 1; break;
                            case "mage": forOnePoint = 2; break;
                            case "enchanteur": forOnePoint = 1; break;
                        }
                        value += calculatedStatistics.Single(e => e.Key.Name == "force").Value / forOnePoint;
                        break;
                    case "puissance magique":
                        switch (className)
                        {
                            case "guerrier": forOnePoint = 2; break;
                            case "chasseur": forOnePoint = 1; break;
                            case "mage": forOnePoint = 2; break;
                            case "enchanteur": forOnePoint = 1; break;
                        }
                        value += calculatedStatistics.Single(e => e.Key.Name == "esprit").Value / forOnePoint;
                        break;
                    case "vie":
                        switch (className)
                        {
                            case "guerrier": forOnePoint = 0.1f; break;
                            case "chasseur": forOnePoint = 0.07f; break;
                            case "mage": forOnePoint = 0.07f; break;
                            case "enchanteur": forOnePoint = 0.07f; break;
                        }
                        value += calculatedStatistics.Single(e => e.Key.Name == "endurance").Value / forOnePoint;
                        break;
                    case "mana":
                        switch (className)
                        {
                            case "guerrier": forOnePoint = 0.05f; break;
                            case "chasseur": forOnePoint = 0.08f; break;
                            case "mage": forOnePoint = 0.15f; break;
                            case "enchanteur": forOnePoint = 0.1f; break;
                        }
                        value += calculatedStatistics.Single(e => e.Key.Name == "intelligence").Value / forOnePoint;
                        break;
                    case "toucher":
                        switch (className)
                        {
                            case "guerrier": forOnePoint = 2; break;
                            case "chasseur": forOnePoint = 2; break;
                            case "mage": forOnePoint = 2; break;
                            case "enchanteur": forOnePoint = 2; break;
                        }
                        value += calculatedStatistics.Single(e => e.Key.Name == "dextérité").Value / forOnePoint;
                        value = value > 1 ? 1 : value;
                        break;
                    case "critique":
                        switch (className)
                        {
                            case "guerrier": forOnePoint = 20; break;
                            case "chasseur": forOnePoint = 20; break;
                            case "mage": forOnePoint = 15; break;
                            case "enchanteur": forOnePoint = 10; break;
                        }
                        value += calculatedStatistics.Single(e => e.Key.Name == "dextérité").Value / forOnePoint;
                        value = value > 0.8f ? 0.8f : value;
                        break;
                    case "esquive":
                        switch (className)
                        {
                            case "guerrier": forOnePoint = 15; break;
                            case "chasseur": forOnePoint = 50; break;
                            case "mage": forOnePoint = 50; break;
                            case "enchanteur": forOnePoint = 15; break;
                        }
                        value += calculatedStatistics.Single(e => e.Key.Name == "dextérité").Value / forOnePoint;
                        value = value > 0.75f ? 0.75f : value;
                        break;
                }

                calculatedStatistics.Add(statistic.Key, value);
                box = new Box(Vector2.Zero, Vector2.One, Color.Transparent, new Color(0, 150, 200, 180));
            }
        }

        /// <summary>
        /// Everybody
        /// </summary>
        public byte level;
        /// <summary>
        /// Everybody
        /// </summary>
        public Dictionary<DB_PointBar, int> pointBars;
        /// <summary>
        /// Everybody
        /// </summary>
        public DB_CharacterRace characterRace;
        /// <summary>
        /// Everybody
        /// </summary>
        public Dictionary<DB_Statistic, float> baseStatistics;
        /// <summary>
        /// Everybody
        /// </summary>
        public List<Effect> effects;
        /// <summary>
        /// Server + Me
        /// </summary>
        public List<Ability> abilities;
        /// <summary>
        /// Everybody
        /// </summary>
        public Dictionary<DB_Statistic, float> calculatedStatistics;
        /// <summary>
        /// Everybody
        /// </summary>
        public bool isDead;
        /// <summary>
        /// Everybody
        /// </summary>
        public Box box;
        /// <summary>
        /// Everybody
        /// </summary>
        public String name;
        /// <summary>
        /// Everybody
        /// </summary>
        public KeyValuePair<Ability, Character> casting = new KeyValuePair<Ability,Character>();
        /// <summary>
        /// Everybody
        /// </summary>
        public int friendshipLevelId;

        public bool isVisible(Vector2 target)
        {
            bool visible = false;

            switch ((int)orientation.X)
            {
                case -1:
                    if (target.X - position.X <= 0)
                    {
                        visible = true;
                    }
                    break;
                case 0:
                    visible = true;
                    break;
                case 1:
                    if (target.X - position.X >= 0)
                    {
                        visible = true;
                    }
                    break;
            }

            if (visible)
            {
                switch ((int)orientation.Y)
                {
                    case -1:
                        if (!(target.Y - position.Y <= 0))
                        {
                            visible = false;
                        }
                        break;
                    case 1:
                        if (!(target.Y - position.Y >= 0))
                        {
                            visible = false;
                        }
                        break;
                }
            }

            return visible;
        }
        public virtual void Cast(GameTime gameTime)
        {
            casting.Key.castTimeLeft = casting.Key.castTimeLeft.Subtract(gameTime.ElapsedGameTime);
            if(casting.Key.castTimeLeft.TotalMilliseconds < 0)
            {
                casting.Key.castTimeLeft = new TimeSpan(0);
                casting.Key.castTimeLeft = casting.Key.castTimeLeft.Add(casting.Key.ability.CastTime);
                if (true)
                {
                    casting.Key.cooldownLeft = casting.Key.cooldownLeft.Add(casting.Key.ability.Cooldown);
                }
            }
        }
        public virtual void Perform()
        {
            
        }
        public virtual void Launch(Ability ability, Character target)
        {
            foreach (KeyValuePair<DB_PointBar, int> kvpPBint in ability.ability.Cost)
            {
                pointBars[kvpPBint.Key] -= kvpPBint.Value;
            }
        }
        public void ChangeStat(Dictionary<DB_Statistic, float> stats, String key, float newValue)
        {
            KeyValuePair<DB_Statistic, float> stat = stats.Single(e => e.Key.Name == key);
            float oldValue = stat.Value;
            stats.Remove(stat.Key);

            stats.Add(stat.Key, newValue);
        }

        public override void Draw(Game game, SpriteBatch spriteBatch)
        {
            base.Draw(game, spriteBatch);
            box.position = position;
            if (toDraw != null)
            {
                box.dimension = new Vector2(toDraw.Width + 2, toDraw.Height + 2);
            }
            box.UpdateBox();
            box.DrawAsCenter(spriteBatch);
        }
    }
}
